package cn.always.xiajia.framework.web.config;

import javax.annotation.Resource;
import javax.servlet.Filter;

import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import cn.always.xiajia.framework.common.enums.WebFilterOrderEnum;
import cn.always.xiajia.framework.web.core.filter.CacheRequestBodyFilter;

@AutoConfiguration
@EnableConfigurationProperties(WebProperties.class)
public class XiaJiaWebAutoConfiguration implements WebMvcConfigurer {

	@Resource
	private WebProperties webProperties;

	@Override
	public void configurePathMatch(PathMatchConfigurer configurer) {
		configurePathMatch(configurer, webProperties.getAdminApi());
		configurePathMatch(configurer, webProperties.getAppApi());
	}

	/**
	 * 设置 API 前缀，仅仅匹配 controller 包下的
	 *
	 * @param configurer 配置
	 * @param api API 配置
	 */
	private void configurePathMatch(PathMatchConfigurer configurer, WebProperties.Api api) {
		// 仅仅匹配controller包
		AntPathMatcher antPathMatcher = new AntPathMatcher(".");
		configurer.addPathPrefix(api.getPrefix(), clazz -> clazz.isAnnotationPresent(RestController.class)
				&& antPathMatcher.match(api.getController(), clazz.getPackage().getName()));
	}

	// /**
	// * 记录日志用的
	// *
	// * @param ApiErrorLogFrameworkService
	// * @return
	// */
	// @Bean
	// public GlobalExceptionHandler
	// globalExceptionHandler(ApiErrorLogFrameworkService
	// ApiErrorLogFrameworkService) {
	// return new GlobalExceptionHandler(applicationName,
	// ApiErrorLogFrameworkService);
	// }

	// @Bean
	// public GlobalResponseBodyHandler globalResponseBodyHandler() {
	// return new GlobalResponseBodyHandler();
	// }

	// ========== Filter 相关 ==========

	/**
	 * 创建 CorsFilter Bean，解决跨域问题
	 */
	@Bean
	public FilterRegistrationBean<CorsFilter> corsFilterBean() {
		// 创建 CorsConfiguration 对象
		CorsConfiguration config = new CorsConfiguration();
		config.setAllowCredentials(true);
		config.addAllowedOriginPattern("*"); // 设置访问源地址
		config.addAllowedHeader("*"); // 设置访问源请求头
		config.addAllowedMethod("*"); // 设置访问源请求方法
		// 创建 UrlBasedCorsConfigurationSource 对象
		UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
		source.registerCorsConfiguration("/**", config); // 对接口配置跨域设置
		return createFilterBean(new CorsFilter(source), WebFilterOrderEnum.CORS_FILTER);
	}

	/**
	 * 创建 RequestBodyCacheFilter Bean，可重复读取请求内容
	 */
	@Bean
	public FilterRegistrationBean<CacheRequestBodyFilter> requestBodyCacheFilter() {
		return createFilterBean(new CacheRequestBodyFilter(), WebFilterOrderEnum.REQUEST_BODY_CACHE_FILTER);
	}

	/**
	 * 设置排序
	 * 
	 * @param <T>
	 * @param filter
	 * @param order
	 * @return
	 */
	public static <T extends Filter> FilterRegistrationBean<T> createFilterBean(T filter, Integer order) {
		FilterRegistrationBean<T> bean = new FilterRegistrationBean<>(filter);
		bean.setOrder(order);
		return bean;
	}
}
